//package com.dbms;
//
//import com.dbms.catalog.Catalog;
//import com.dbms.common.Column;
//import com.dbms.common.Schema;
//import com.dbms.common.Tuple;
//import com.dbms.common.Type;
//import com.dbms.execution.execution.CreateTableExecutor;
//import com.dbms.execution.execution.Executor;
//import com.dbms.execution.execution.InsertExecutor;
//import com.dbms.storage.BufferPoolManager;
//import com.dbms.storage.DiskManager;
//import com.dbms.storage.Page;
//import com.dbms.storage.TablePage;
//import com.dbms.transaction.LogManager;
//
//import java.io.File;
//import java.io.IOException;
//import java.util.Collections;
//import java.util.List;
//
///**
// * 一个用于演示多数据页表顺序扫描功能的独立测试程序。
// * 本程序将展示当一个表的数据量超过单个页面的容量时，
// * 新页面是如何被创建和链接的，以及SeqScanExecutor是如何
// * 正确地遍历这些链接的页面以读取所有数据的。
// */
//public class SequentialScanTest {
//
//    public static void main(String[] args) throws IOException {
//        String dbFileName = "sequential_scan_test.db";
//        String logFileName = "sequential_scan_test.log";
//
//        System.out.println("============== 多页表顺序扫描功能演示开始 ==============\n");
//
//        // --- 1. 初始化环境 ---
//        System.out.println("--- 1. 初始化环境 ---");
//        new File(dbFileName).delete();
//        new File(logFileName).delete();
//
//        DiskManager diskManager = new DiskManager(dbFileName);
//        LogManager logManager = new LogManager(logFileName);
//        BufferPoolManager bpm = new BufferPoolManager(20, diskManager, logManager);
//        Catalog catalog = new Catalog(bpm, true);
//        System.out.println("初始化完成！\n");
//
//        // --- 2. 创建一个表 ---
//        System.out.println("--- 2. 创建表 'logs' ---");
//        // 使用一个较大的VARCHAR来快速填满页面
//        Schema schema = new Schema(List.of(
//                new Column("log_id", Type.INTEGER),
//                new Column("log_message", Type.VARCHAR, 200)
//        ));
//        Executor createTableExec = new CreateTableExecutor(catalog, "logs", schema);
//        createTableExec.open();
//        createTableExec.next();
//        createTableExec.close();
//        System.out.println("表 'logs' 创建成功，其数据将从根页面 " + catalog.getTable("logs").rootPageId + " 开始存储。\n");
//
//        // --- 3. 插入大量数据，直到触发页面分裂 ---
//        System.out.println("--- 3. 插入大量数据以填满多个页面 ---");
//        Catalog.TableMetadata logTable = catalog.getTable("logs");
//        // 根据Schema粗略计算，每条记录约 4 + 4 + 200 = 208字节
//        // 4096字节的页面大约能存 19 条记录。我们插入40条来确保至少跨越3个页面。
//        int recordsToInsert = 40;
//        for (int i = 1; i <= recordsToInsert; i++) {
//            String message = "这是一条日志消息，编号为 " + i + "。我们用足够长的文本来填充空间，以确保能够快速地填满一个数据页，从而触发新的页面分配和链接机制。";
//            Tuple tuple = new Tuple(List.of(i, message), schema);
//            Executor insertExec = new InsertExecutor(bpm, logTable, Collections.singletonList(tuple));
//            insertExec.open();
//            insertExec.next();
//            insertExec.close();
//        }
//        bpm.flushAllPages();
//        System.out.println(recordsToInsert + " 条记录插入完毕。\n");
//
//        // --- 4. 执行多页顺序扫描 ---
//        System.out.println("--- 4. 执行顺序扫描 (Sequential Scan) ---");
//        System.out.println("    预期: 扫描器将从根页面开始，沿着页面间的链接，访问所有页面。");
//
//        // 创建一个我们自己的、带有演示信息打印的扫描器
//        int count = demonstrateScan(bpm, logTable);
//
//        System.out.println("\n--- 5. 验证扫描结果 ---");
//        System.out.println("    共扫描到 " + count + " 条记录。");
//        if (count == recordsToInsert) {
//            System.out.println("    ✅ 成功！扫描到的记录数与插入的记录数一致！");
//        } else {
//            System.out.println("    ❌ 失败！扫描到的记录数与插入的记录数不匹配！");
//        }
//
//        System.out.println("\n============== 演示结束 ==============");
//    }
//
//    /**
//     * 这是一个为了演示而特别创建的扫描逻辑。
//     * 它模仿了 SeqScanExecutor 的核心行为，但增加了打印语句来显示页面跳转的过程。
//     * @param bpm BufferPoolManager实例
//     * @param tableInfo 要扫描的表
//     * @return 扫描到的元组总数
//     * @throws IOException
//     */
//    private static int demonstrateScan(BufferPoolManager bpm, Catalog.TableMetadata tableInfo) throws IOException {
//        int count = 0;
//        int currentPageId = tableInfo.rootPageId;
//        Page currentPage;
//
//        while (currentPageId != TablePage.INVALID_PAGE_ID) {
//            System.out.println("    --> 正在扫描 Page " + currentPageId + "...");
//            currentPage = bpm.fetchPage(currentPageId);
//            currentPage.rLock();
//
//            TablePage tableView = new TablePage(currentPage);
//            int tuplesInPage = 0;
//            for (int i = 0; i < tableView.getSlotCount(); i++) {
//                if (tableView.getTuple(i) != null) {
//                    count++;
//                    tuplesInPage++;
//                }
//            }
//            System.out.println("        Page " + currentPageId + " 中找到 " + tuplesInPage + " 条记录。");
//
//            int nextPageId = tableView.getNextPageId();
//
//            currentPage.rUnlock();
//            bpm.unpinPage(currentPageId, false);
//
//            currentPageId = nextPageId;
//        }
//        return count;
//    }
//}